package com.example.aop;

import com.example.annotation.FlowControl;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 流控拦截器
 * @author long
 */
@Component
public class FlowControlInterceptor implements HandlerInterceptor {

    @Resource
    private RedisTemplate<String,Long> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if(!(handler instanceof HandlerMethod)){
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        FlowControl flowControl = method.getAnnotation(FlowControl.class);
        // 方法上面没有加注解 则不拦截
        if (Objects.isNull(flowControl)) {
            return true;
        }

        String uri = request.getRequestURI();
        String remoteAddr = request.getRemoteAddr();
        String redisKey = flowControl.prefix()+"::"+uri+remoteAddr;

        Long redisValue = redisTemplate.opsForValue().increment(redisKey, flowControl.expire());
        System.out.println("访问次数:"+redisValue);

        // 第一次访问
        if(redisValue == null || redisValue == 1L){
            redisTemplate.expire(redisKey,flowControl.expire(), TimeUnit.SECONDS);
        }else if(redisValue > flowControl.limit()){
            throw new RuntimeException("服务器繁忙，请稍候再试");
        }

        return true;
    }

}
